package com.wechat.share;

import com.google.gson.Gson;
import com.nsi.util.RedisUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.net.ConnectException;
import java.net.URL;
import java.security.MessageDigest;
import java.util.Formatter;
import java.util.HashMap;
import java.util.UUID;

/**
 * 微信分享工具类
 *
 * @author Luo Zhen
 * @create 2018-08-07
 **/
public class WxchatShareUtil {

    private static Logger logger = LoggerFactory.getLogger(WxchatShareUtil.class);
    private static final String ACCESS_TOKEN = "access_token";
    private static final String TICKET = "ticket";

    /**
     * 验签逻辑
     *
     * @param url
     * @return
     */
    public static HashMap<String, String> wxChatSign(String url) {
        //获取accessToken
        String accessToken = WxchatShareUtil.weChatShareParem(WechatShareConfig.requestUrl_ACCESS_TOKEN, "GET", "", WxchatShareUtil.ACCESS_TOKEN);
        //jsapi_ticket复用全局缓存
        String jsapi_ticket = null;
        //redis取出时间转换整数
        long propertyTime = Long.parseLong(RedisUtils.searchRedis("ticket_time"));
        //当前时间取整转换证书
        long nowTime = System.currentTimeMillis();

        //相差大于2小时 7200000
        if (nowTime - propertyTime > 7000000) {
            //重新定义url
            String requestUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";
            //发送请求
            jsapi_ticket = WxchatShareUtil.weChatShareParem(requestUrl, "GET", "", WxchatShareUtil.TICKET);
            //修改redis参数
            RedisUtils.alterRedis("ticket_time", String.valueOf(nowTime));
            RedisUtils.alterRedis("jsapi_ticket", jsapi_ticket);
        } else {
            //取值
            jsapi_ticket = RedisUtils.searchRedis("jsapi_ticket");
        }
        //生成字符串
        String nonceStr = UUID.randomUUID().toString();
        //生成时间戳
        String timeStamp = Long.toString(System.currentTimeMillis() / 1000);
        //签名算法并有序
        String str = new StringBuffer()
                .append("jsapi_ticket=")
                .append(jsapi_ticket)
                .append("&noncestr=")
                .append(nonceStr)
                .append("&timestamp=")
                .append(timeStamp)
                .append("&url=")
                .append(url).toString();

        //SHA-1验签算法
        MessageDigest crypt = null;
        try {
            crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(str.getBytes("UTF-8"));
        } catch (Exception e) {
            logger.error("【微信分享】验签算法异常: {}, 验签字符串: {}", e.getMessage(), str);
        }
        String signature = byteToHex(crypt.digest());

        HashMap<String, String> resultMap = new HashMap<>();
        resultMap.put("appId", WechatShareConfig.APPID);
        resultMap.put("timestamp", timeStamp);
        resultMap.put("nonceStr", nonceStr);
        resultMap.put("signature", signature);
        return resultMap;
    }


    /**
     * 字节转换
     *
     * @param hash
     * @return
     */
    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    /**
     * 微信分享依赖方法-获取access_token
     *
     * @param requestUrl
     * @param requestMethod
     * @param outputStr
     * @return
     */
    private static String weChatShareParem(String requestUrl, String requestMethod, String outputStr, String respStr) {
        String WechatId = null;
        StringBuffer buffer = new StringBuffer();
        //获取access_token
        try {
            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            // 设置请求方式（GET/POST）
            httpUrlConn.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod)) {
                httpUrlConn.connect();
            }
            // 当有数据需要提交时
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式，防止中文乱码
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }
            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            httpUrlConn.disconnect();

            Gson gson = new Gson();
            String WechatJson = gson.toJson(buffer.toString());

            if ("access_token".equals(respStr)) {
                WechatId = WechatJson.substring(WechatJson.indexOf(WxchatShareUtil.ACCESS_TOKEN) + 17, WechatJson.indexOf("expires_in") - 5);
            } else {
                WechatId = WechatJson.substring(WechatJson.indexOf(WxchatShareUtil.TICKET) + 11, WechatJson.indexOf("expires_in") - 5);
            }
        } catch (ConnectException ce) {
            logger.error("【微信分享】msg:{}", ce.getMessage());
        } catch (Exception e) {
            logger.error("【微信分享】msg:{}", e.getMessage());
        }
        return WechatId;
    }
}
